<?php
namespace service;

use think\facade\Log as FacadeLog;
use think\Service;

/**
 * 异步服务，通过直接返回缓冲区内容，保留脚本运行实现一定程度的异步处理减少响应等待
 */
class AsyncService extends Service
{
    //下标2 默认表示用call_user_func_array调用，1 表示是单例模式通过app容器调用
    private $asyncArr = [
        ['yklog','oplog',1],
        [AsyncTaskService::class,'send',0],
    ];

    /**
     * 注册服务和中间件
     *
     * @return void
     */
    public function register()
    {
        $this->app->middleware->add(AsyncService::class);
    }

    /**
     * 中间件入口
     *
     * @param \think\Request $request
     * @param \Closure $next
     * @return void
     */
    public function handle($request, \Closure $next)
    {
        return $next($request);
    }

    /**
     * 结束调度后触发日志记录
     *
     * @param array $response
     * @return void
     */
    public function end($response){

        ini_set('max_execution_time', '0');

        $webServer = $this->queryWebServer();

        if ($webServer == 'nginx') {
            fastcgi_finish_request();
        } else if ($webServer == 'apache') {
            header("Connection: close");
            header('Content-Length: ' . ob_get_length());
    
            ob_flush();
            flush();
        }

        ignore_user_abort(true);
        set_time_limit(0);

        try {
            foreach ($this->asyncArr as $value) {
                switch ($value[2]) {
                    case '1':
                        $method = $value[1];
                        app($value[0])->$method($response);
                        break;
                    
                    default:
                        call_user_func([$value[0],$value[1]],$response);
                        break;
                }
            }
        } catch (\Throwable $th) {        
            FacadeLog::error("[记录日志异常] ".$th->getMessage());
        }
        
    }

     /**
     * 查询web服务器类型
     *
     * @return void
     */
    private function queryWebServer()
    {
        $sapi = PHP_SAPI;
        $val = null;
        switch ($sapi) {
            case 'fpm-fcgi':
                $val = 'nginx';
                break;
            case 'cgi-fcgi':
                $val = 'nginx';
                break;
            case 'apache2handler':
                $val = 'apache';
                break;
            case 'cli':
                $val = 'cli';
                break;
            default:
                $val = $sapi;
                break;
        }
        return $val;
    }

}